home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Testing & Debugging / Debuggers & dcmds / Robix & sources / robix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-17  |  10.2 KB  |  468 lines  |  [TEXT/MPS ]

  1. /*
  2. *
  3. * © Copyright 1982-1992, Rob Glanville
  4. *
  5. * by Rob Glanville
  6. *
  7. * 07 Sep 92 - V1.02
  8. *
  9. * robix.c - Debugger foundation
  10. *
  11. */
  12.  
  13. #include <stdio.h> /* Only needed when running under an O.S. */
  14.  
  15. #define UInt8        unsigned char
  16. #define UInt16        unsigned short
  17. #define UInt32        unsigned long
  18. #define True        0xffffffff
  19. #define False        0x00000000
  20. #define CR            0x0d
  21. #define LF            0x0a
  22. #define    Rubout        0x08
  23. #define Tab            0x09
  24. #define NOP            0x00
  25. #define Null        0x00
  26. #define Blank        0x20
  27.  
  28. /************************************* Variables *********************************************/
  29.  
  30. UInt8 CommandLine[256];    /* Input buffer                                */
  31. UInt8 delimiter;        /* Delimiter between arguments                */
  32. UInt8 AsciiBuf[19];        /* A buffer for output                        */
  33. UInt8 Argument[0x80];    /* The arguments go here one by one            */
  34. UInt8 TabSize;            /* Size of tab stops                        */
  35.  
  36. UInt16 ArgSize;            /* Argument size                            */
  37. UInt16 CPointer;        /* Command pointer                            */
  38. UInt16 slotPtr;            /* A logical index to the slot where 1=9    */
  39.  
  40. UInt32 CommandIndex;    /* The index into command buffer            */
  41. UInt32 number;            /* A place for all numbers input            */
  42. UInt32 BufPtr;            /* Alias buffer pointer for unions            */
  43. UInt32 RobBase;
  44.  
  45. /************************************* Constants *********************************************/
  46.  
  47. UInt8 Digits[]     = {"0123456789ABCDEF"};
  48. UInt8 Delimiters[] = {0x09,0x0a,0x1b,0x20,0x21,0x22,0x23,0x24,0x25,0x26,
  49.                       0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x3a,
  50.                       0x3b,0x3c,0x3d,0x3e,0x40,0x5b,0x5c,0x5d,0x5e,0x5f,
  51.                       0x00,0x60,0x7b,0x7c,0x7d,0x7e,0x7f,0x3f,0x0d};
  52.  
  53. /************************************* Routines **********************************************/
  54.  
  55. /*
  56.  getch and putchar are the only interface that needs to be modified for
  57.  different environments. If you don't have an O.S. to call then you have
  58.  to write these routines yourself and they would talk directly to hardware.
  59. */
  60. unsigned char getch() {
  61.     UInt8 character;
  62.     do {
  63.         character = getchar();
  64.         } while (character == 0xff);
  65.     return(character);
  66.     }
  67.  
  68. void printstr(string)
  69.     UInt8 *string;
  70.     {
  71.     while (*string != Null) putchar(*string++);
  72.     }
  73.  
  74. void SyntaxError() {
  75.     printstr("Syntax error\n");
  76.     }
  77.  
  78. /*
  79.  LineIn get input from the user and places it in a command lime buffer
  80.  for later parsing. This is nothing more than echo characters with rubouts
  81.  and tabs.
  82. */
  83. void LineIn() {
  84.     UInt8 character,exit;
  85.     UInt16 index,TabSpace;
  86.     if (delimiter == CR) {
  87.         CommandIndex = Null;
  88.         exit = False;
  89.         CPointer = Null;
  90.         do {
  91.             character = getch();
  92.             if (character ==  Rubout) {
  93.                 if (CommandIndex > 0) {
  94.                     putchar(Rubout);
  95.                     putchar(Blank);
  96.                     putchar(Rubout);
  97.                     CommandIndex--;
  98.                     }
  99.                 }
  100.             else if (character == CR) {
  101.                 putchar(CR); /* */
  102.                 CommandLine[CommandIndex++] = CR;
  103.                 exit = True;        
  104.                 }
  105.             else if (character == Tab) {
  106.                 TabSpace = TabSize - ((CommandIndex+1) % TabSize);
  107.                 for (index=0;index<TabSpace;index++) {
  108.                     putchar(Blank);
  109.                     CommandLine[CommandIndex++] = Blank;
  110.                     }
  111.                 }
  112.             else {
  113. /*                putchar(character); /* Some interfaces like MPW already echo the characters */
  114.                 CommandLine[CommandIndex++] = character;
  115.                 }
  116.             } while (!exit);
  117.         }
  118.     else delimiter = CR;
  119.     }
  120.  
  121. /*
  122.  Takes a pointer to a character and changes lower case to upper case.
  123. */
  124. void Upper(character) UInt8 *character; {
  125.     if ((*character >= 'a') && (*character <= 'z')) *character -= Blank;
  126.     }
  127.  
  128. /*
  129.  ScanDelimiters simply sets the command line pointer to point to the
  130.  first non delimiter so the user can type garbage and there won't be
  131.  a syntax error.
  132. */
  133. void ScanDelimiters() {
  134.     UInt16 index;
  135.     UInt8 found;
  136.     do {
  137.         found = False;
  138.         for (index=0;index<sizeof(Delimiters)-2;index++) {
  139.             if (CommandLine[CPointer] == Delimiters[index]) found = True;
  140.             }
  141.         if (found) CPointer++;
  142.         } while (found);
  143.     }
  144.  
  145. /*
  146.  getarg simply parses the command line and places and arguments in
  147.  a buffer called 'Argument'. Whatever delimiter is found is placed
  148.  in 'delimiter' and the variable 'ArgSize' has the byte count of
  149.  the argument. You make a call to getarg and check the size for non-zero
  150.  to tell when one is found. Keep making calls until you get an argument
  151.  or the delimiter is a cursor return which indicates the end of the
  152.  command line. If you want a number, then use GetValue.
  153. */
  154. void getarg() {
  155.     UInt16 index,ArgPtr;
  156.     UInt8 found;
  157.     ArgPtr = Null;
  158.     do {
  159.         found = False;
  160.         for (index=0;index<sizeof(Delimiters);index++) {
  161.             if (CommandLine[CPointer] == Delimiters[index]) {
  162.                 delimiter = Delimiters[index];
  163.                 if (delimiter != CR) CPointer++;
  164.                 found = True;
  165.                 break;
  166.                 }
  167.             }
  168.         if (!found) Argument[ArgPtr++] = CommandLine[CPointer++];
  169.         } while (!found);
  170.     Argument[ArgPtr] = Null;
  171.     ArgSize = ArgPtr;
  172.     }
  173.  
  174. /*
  175.  GetValue returns true if a hexadecimal number was found in the
  176.  command line. Otherwise it returns false. If a nubmer is found,
  177.  it is placed in the global variable called 'number'. Repeated
  178.  calls to GetValue will get multiple parameters to use in a command. 
  179. */
  180. UInt16 GetValue() {
  181.     UInt8 found;
  182.     UInt16 index,loop;
  183.     if (delimiter == ',') return(False);
  184.     found = False;
  185.     number = Null;
  186.     do {
  187.         getarg(); /* Get one argument from the command line */
  188.         if (ArgSize) {
  189.             /* Check for all digits in the argument */
  190.             for (index=0;index<ArgSize;) {
  191.                 Upper(&Argument[index]);
  192.                 found = False;
  193.                 for (loop=0;loop<0x10;loop++) {
  194.                     if (Argument[index] == Digits[loop]) {
  195.                         Argument[index] = loop;
  196.                         found = True;
  197.                         break;
  198.                         }
  199.                     }
  200.                 if (!found) break;
  201.                 else index++;
  202.                 }
  203.             /* Convert ascii to hex */
  204.             if (found) for (index=0;index<ArgSize;index++) {
  205.                 number = ((number * 0x10) + Argument[index]);
  206.                 }
  207.             }
  208.         } while ((!found) && (delimiter != CR) && (delimiter != ','));
  209.     return(found);
  210.     }
  211.  
  212. void nibble(data) UInt8 data; {
  213.     if (data > 9) putchar(data + '7');
  214.     else putchar(data + '0');
  215.     }
  216.  
  217. void byteout(data) UInt8 data; {
  218.     nibble((data / 0x10) & 0x0f);
  219.     nibble(data & 0x0f);
  220.     }
  221.  
  222. void wordout(data) UInt16 data; {
  223.     byteout((UInt8)(data / 0x100) & 0xff);
  224.     byteout((UInt8)data & 0xff);
  225.     }
  226.  
  227. void longout(data) UInt32 data; {
  228.     wordout((UInt16)(data / 0x10000) & 0xffff);
  229.     wordout((UInt16)data & 0xffff);
  230.     }
  231.  
  232. void crlf() { printstr("\n"); }
  233.  
  234. /************************************* Commands *********************************************/
  235.  
  236. /*
  237.  AlterMemory gets the address and data from the command line and
  238.  alters that location. If no data is given the the user is prompted
  239.  for it.
  240. */
  241. UInt16 AlterMemory() {
  242.     UInt32 Address;
  243.     UInt8 databyte;
  244.     if (!GetValue()) return(True);
  245.     Address = number;
  246.     if (GetValue()) {
  247.         do {
  248.             *(UInt8 *)Address++ = number;
  249.             } while (GetValue());
  250.         return(False);
  251.         }
  252.     else while(True) {
  253.         longout(Address);
  254.         putchar(Blank);
  255.         databyte = *(UInt8 *)Address;
  256.         byteout(databyte);
  257.         putchar('-');
  258.         LineIn(); /* Get input from user for next value */
  259.         ScanDelimiters();
  260.         if (!GetValue()) return(False);
  261.         *(UInt8 *)Address++ = number;
  262.         }
  263.     }
  264.  
  265. UInt16 DisplayMemory() {
  266.     UInt32 Start,Length,index,Aindex,Sindex;
  267.     register UInt8 databyte;
  268.     if (!GetValue()) return(True);
  269.     Start = number;
  270.     if (GetValue()) Length = number;
  271.     else Length = 0x10;
  272.     if (Length == 0) Length = 1;
  273.     index = Null;
  274.     Aindex = Null;
  275.     do {
  276.         if ((index % 0x10) == 0x00) longout(Start);
  277.         putchar(Blank);
  278.         databyte = *(UInt8 *)Start;
  279.         if ((databyte >= Blank) && (databyte <= 0x7e)) AsciiBuf[Aindex++] = databyte;
  280.         else AsciiBuf[Aindex++] = '.';
  281.         Start++;
  282.         byteout(databyte);
  283.         if ((index % 0x10) == 0x0f) {
  284.             AsciiBuf[16] = CR;
  285.             AsciiBuf[17] = Null;
  286.             putchar(Blank);
  287.             putchar(Blank);
  288.             printstr(&AsciiBuf);
  289.             Aindex = Null;
  290.             }
  291.         } while (++index<Length);
  292.     if ((index % 0x10) != Null) {
  293.         Sindex = 0x10 - (index % 0x10);
  294.         for (index=0;index<Sindex;index++) printstr("   ");
  295.         AsciiBuf[Aindex] = Null;
  296.         printstr("  ");
  297.         printstr(&AsciiBuf);
  298.         crlf();
  299.         }
  300.     return(False);
  301.     }
  302.  
  303. UInt16 FillMemory() {
  304.     UInt32 Start,Length,Value,index;
  305.     UInt8 increment;
  306.     if (!GetValue()) return(True);
  307.     Start = number;
  308.     if (!GetValue()) return(True);
  309.     Length = number;
  310.     if (Length == 0) Length = 1;
  311.     if (!GetValue()) {
  312.         if (Argument[0] == 'I') {
  313.             increment = True;
  314.             Value = 0;
  315.             }
  316.         else return(True);
  317.         }
  318.     else {
  319.         increment = False;
  320.         Value = number;
  321.         }
  322.     for (index=0;index<Length;index++) {
  323.         *(UInt8 *)Start++ = Value;
  324.         if (increment) Value++;
  325.         }
  326.     return(False);
  327.     }
  328.  
  329. /* Fill in the help menu when you add a new command */
  330. void Help() {
  331.     printstr("?) Print this menu\n");
  332.     printstr("A) Alter memory\n");
  333. /*    printstr("B) \n"); */
  334. /*    printstr("C) \n"); */
  335.     printstr("D) Display memory\n");
  336. /*    printstr("E) \n"); */
  337.     printstr("F) Fill memory\n");
  338. /*    printstr("G) \n"); */
  339. /*    printstr("H) \n"); */
  340. /*    printstr("I) \n"); */
  341. /*    printstr("J) \n"); */
  342. /*    printstr("K) \n"); */
  343. /*    printstr("L) \n"); */
  344. /*    printstr("M) \n"); */
  345. /*    printstr("N) \n"); */
  346. /*    printstr("O) \n"); */
  347. /*    printstr("P) \n"); */
  348. /*    printstr("Q) \n"); */
  349. /*    printstr("R) \n"); */
  350. /*    printstr("S) \n"); */
  351. /*    printstr("T) \n"); */
  352. /*    printstr("U) \n"); */
  353. /*    printstr("V) \n"); */
  354. /*    printstr("W) \n"); */
  355. /*    printstr("X) \n"); */
  356. /*    printstr("Y) \n"); */
  357. /*    printstr("Z) \n"); */
  358.     }
  359.  
  360. /************************************* Main Loop ********************************************/
  361.  
  362. void main() {
  363.     UInt8 Exit;
  364.     delimiter = CR;
  365.     TabSize = 8;
  366.     Exit = False;
  367.     printstr("ROBIX\n");
  368.     while (!Exit) {
  369.         if (delimiter == CR) printstr(">");
  370.         LineIn();
  371.         ScanDelimiters(); /* Point to first non Blank */
  372.         Upper(&CommandLine[CPointer]);
  373.         switch(CommandLine[CPointer++]) {
  374.             case '?' :
  375.                 Help();
  376.                 break;
  377.             case CR :
  378.                 break;
  379.             case 'A' :
  380.                 if (AlterMemory()) SyntaxError();
  381.                 break;
  382. /*            case 'B' :
  383.                 break;
  384.             case 'C' :
  385.                 break;
  386. */            case 'D' :
  387.                 if (DisplayMemory()) SyntaxError();
  388.                 break;
  389. /*            case 'E' :
  390.                 break;
  391. */            case 'F' :
  392.                 if (FillMemory()) SyntaxError();
  393.                 break;
  394. /*            case 'G' :
  395.                 break;
  396.             case 'H' :
  397.                 break;
  398.             case 'I' :
  399.                 break;
  400.             case 'J' :
  401.                 break;
  402.             case 'K' :
  403.                 break;
  404.             case 'L' :
  405.                 break;
  406.             case 'M' :
  407.                 break;
  408.             case 'N' :
  409.                 break;
  410.             case 'O' :
  411.                 break;
  412.             case 'P' :
  413.                 break;
  414.             case 'Q' :
  415.                 break;
  416.             case 'R' :
  417.                 break;
  418.             case 'S' :
  419.                 break;
  420.             case 'T' :
  421.                 break;
  422.             case 'U' :
  423.                 break;
  424.             case 'V' :
  425.                 break;
  426.             case 'W' :
  427.                 break;
  428.             case 'X' :
  429.                 break;
  430.             case 'Y' :
  431.                 break;
  432.             case 'Z' :
  433.                 break;
  434. */            default :
  435.                 printstr("Unknown command\n");
  436.                 delimiter = CR;
  437.                 break;
  438.             }
  439.         }
  440.     }
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.